home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / mac / DirectX SDK / DXSDK / samples / Multimedia / DirectPlay / LobbyClient / LobbyClient.cpp < prev    next >
C/C++ Source or Header  |  2001-10-31  |  43KB  |  1,082 lines

  1. //----------------------------------------------------------------------------
  2. // File: LobbyClient.cpp
  3. //
  4. // Desc: LobbyClient is a simple lobby client.  It displays all registered DirectPlay 
  5. //       applications on the local system.  It allows the 
  6. //       user to launch one or more of these applications using a chosen 
  7. //       service provider.  A launched lobbied application may be told to either 
  8. //       join or host a game.
  9. //
  10. // Copyright (c) 1999-2001 Microsoft Corp. All rights reserved.
  11. //-----------------------------------------------------------------------------
  12. #define STRICT
  13. #include <winsock.h>
  14. #include <windows.h>
  15. #include <basetsd.h>
  16. #include <dplay8.h>
  17. #include <dplobby8.h>
  18. #include <dpaddr.h>
  19. #include <dxerr8.h>
  20. #include <cguid.h>
  21. #include <tchar.h>
  22. #include "DXUtil.h"
  23. #include "resource.h"
  24.  
  25.  
  26.  
  27. //-----------------------------------------------------------------------------
  28. // Defines, and constants
  29. //-----------------------------------------------------------------------------
  30. #define DPLAY_SAMPLE_KEY        TEXT("Software\\Microsoft\\DirectX DirectPlay Samples")
  31. #define WM_APP_APPDISCONNECTED  (WM_APP + 1)
  32. #define WM_APP_SETSTATUS        (WM_APP + 2)
  33.  
  34.  
  35.  
  36.  
  37. //-----------------------------------------------------------------------------
  38. // Global variables
  39. //-----------------------------------------------------------------------------
  40. IDirectPlay8Peer*  g_pDP                         = NULL;    // DirectPlay peer object
  41. IDirectPlay8LobbyClient* g_pLobbyClient          = NULL;    // DirectPlay lobby client
  42. HINSTANCE          g_hInst                       = NULL;    // HINST of app
  43. HWND               g_hDlg                        = NULL;    // HWND of main dialog
  44. TCHAR              g_strAppName[256]             = TEXT("LobbyClient");
  45. GUID*              g_pCurSPGuid                  = NULL;    // Currently selected guid
  46. TCHAR              g_strPlayerName[MAX_PATH];               // Local player name
  47. TCHAR              g_strSessionName[MAX_PATH];              // Session name
  48. TCHAR              g_strPreferredProvider[MAX_PATH];        // Provider string
  49. TCHAR              g_strLocalIP[MAX_PATH];                  // Provider string
  50.  
  51.  
  52.  
  53.  
  54. //-----------------------------------------------------------------------------
  55. // Function-prototypes
  56. //-----------------------------------------------------------------------------
  57. HRESULT WINAPI   DirectPlayMessageHandler( PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer );
  58. HRESULT WINAPI   DirectPlayLobbyMessageHandler( PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer );
  59. INT_PTR CALLBACK LobbyClientDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
  60. HRESULT          InitDirectPlay();
  61. HRESULT          OnInitDialog( HWND hDlg );
  62. VOID             SetupAddressFields( HWND hDlg );
  63. HRESULT          AllocAndInitConnectSettings( HWND hDlg, GUID* pAppGuid, DPL_CONNECTION_SETTINGS** ppdplConnectSettings );
  64. VOID             FreeConnectSettings( DPL_CONNECTION_SETTINGS* pSettings );
  65. HRESULT          LaunchApp( HWND hDlg );
  66. HRESULT          EnumRegisteredApplications( HWND hDlg );
  67. HRESULT          EnumServiceProviders( HWND hDlg );
  68. HRESULT          EnumAdapters( HWND hDlg, GUID* pSPGuid );
  69. HRESULT          SendMsgToApp( HWND hDlg );
  70. HRESULT          DisconnectFromApp( HWND hDlg );
  71.  
  72.  
  73.  
  74.  
  75.  
  76.  
  77.  
  78. //-----------------------------------------------------------------------------
  79. // Name: WinMain()
  80. // Desc: Entry point for the application.  Since we use a simple dialog for 
  81. //       user interaction we don't need to pump messages.
  82. //-----------------------------------------------------------------------------
  83. INT APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, 
  84.                       LPSTR pCmdLine, INT nCmdShow )
  85. {
  86.     HRESULT hr;
  87.     HKEY    hDPlaySampleRegKey;
  88.  
  89.     g_hInst = hInst; 
  90.  
  91.     // Read persistent state information from registry
  92.     RegCreateKeyEx( HKEY_CURRENT_USER, DPLAY_SAMPLE_KEY, 0, NULL,
  93.                     REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, 
  94.                     &hDPlaySampleRegKey, NULL );
  95.     DXUtil_ReadStringRegKey( hDPlaySampleRegKey, TEXT("Player Name"), 
  96.                              g_strPlayerName, MAX_PATH, TEXT("TestPlayer") );
  97.     DXUtil_ReadStringRegKey( hDPlaySampleRegKey, TEXT("Session Name"), 
  98.                              g_strSessionName, MAX_PATH, TEXT("TestGame") );
  99.     DXUtil_ReadStringRegKey( hDPlaySampleRegKey, TEXT("Preferred Provider"), 
  100.                              g_strPreferredProvider, MAX_PATH, 
  101.                              TEXT("DirectPlay8 TCP/IP Service Provider") );
  102.  
  103.     // Init COM so we can use CoCreateInstance
  104.     CoInitializeEx( NULL, COINIT_MULTITHREADED );
  105.  
  106.     if( FAILED( hr = InitDirectPlay() ) )
  107.     {
  108.         DXTRACE_ERR( TEXT("InitDirectPlay"), hr );
  109.         MessageBox( NULL, TEXT("Failed initializing IDirectPlay8Peer. ")
  110.                     TEXT("The sample will now quit."),
  111.                     g_strAppName, MB_OK | MB_ICONERROR );
  112.         return FALSE;
  113.     }
  114.  
  115.     DialogBox( hInst, MAKEINTRESOURCE(IDD_LOBBY_CLIENT), NULL, 
  116.                (DLGPROC) LobbyClientDlgProc );
  117.  
  118.     if( g_pLobbyClient )
  119.     {
  120.         g_pLobbyClient->Close( 0 );
  121.         SAFE_RELEASE( g_pLobbyClient );
  122.     }
  123.  
  124.     if( g_pDP )
  125.     {
  126.         g_pDP->Close(0);
  127.         SAFE_RELEASE( g_pDP );
  128.     }
  129.  
  130.     CoUninitialize();
  131.  
  132.     // Write information to the registry
  133.     DXUtil_WriteStringRegKey( hDPlaySampleRegKey, TEXT("Player Name"), g_strPlayerName );
  134.     DXUtil_WriteStringRegKey( hDPlaySampleRegKey, TEXT("Session Name"), g_strSessionName );
  135.     DXUtil_WriteStringRegKey( hDPlaySampleRegKey, TEXT("Preferred Provider"), g_strPreferredProvider );
  136.  
  137.     RegCloseKey( hDPlaySampleRegKey );
  138.  
  139.     return TRUE;
  140. }
  141.  
  142.  
  143.  
  144.  
  145. //-----------------------------------------------------------------------------
  146. // Name: InitDirectPlay()
  147. // Desc: 
  148. //-----------------------------------------------------------------------------
  149. HRESULT InitDirectPlay()
  150. {
  151.     HRESULT hr;
  152.  
  153.     // Create and init IDirectPlay8Peer
  154.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Peer, NULL, 
  155.                                        CLSCTX_INPROC_SERVER,
  156.                                        IID_IDirectPlay8Peer, 
  157.                                        (LPVOID*) &g_pDP ) ) )
  158.         return DXTRACE_ERR( TEXT("CoCreateInstance"), hr );
  159.  
  160.     if( FAILED( hr = g_pDP->Initialize( NULL, DirectPlayMessageHandler, 0 ) ) )
  161.         return DXTRACE_ERR( TEXT("Initialize"), hr );
  162.  
  163.     // Create and init IDirectPlay8LobbyClient
  164.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8LobbyClient, NULL, 
  165.                                        CLSCTX_INPROC_SERVER,
  166.                                        IID_IDirectPlay8LobbyClient, 
  167.                                        (LPVOID*) &g_pLobbyClient ) ) )
  168.         return DXTRACE_ERR( TEXT("CoCreateInstance"), hr );
  169.  
  170.     if( FAILED( hr = g_pLobbyClient->Initialize( NULL, DirectPlayLobbyMessageHandler, 0 ) ) )
  171.         return DXTRACE_ERR( TEXT("Initialize"), hr );
  172.  
  173.     return S_OK;
  174. }
  175.  
  176.  
  177.  
  178.  
  179. //-----------------------------------------------------------------------------
  180. // Name: LobbyClientDlgProc()
  181. // Desc: Handles dialog messages
  182. //-----------------------------------------------------------------------------
  183. INT_PTR CALLBACK LobbyClientDlgProc( HWND hDlg, UINT msg, 
  184.                                      WPARAM wParam, LPARAM lParam )
  185. {
  186.     HRESULT hr;
  187.  
  188.     switch( msg ) 
  189.     {
  190.         case WM_INITDIALOG:
  191.         {
  192.             g_hDlg = hDlg;
  193.             if( FAILED( hr = OnInitDialog( hDlg ) ) )
  194.             {
  195.                 DXTRACE_ERR( TEXT("OnInitDialog"), hr );
  196.                 MessageBox( NULL, TEXT("Failed initializing dialog box. ")
  197.                             TEXT("The sample will now quit."),
  198.                             g_strAppName, MB_OK | MB_ICONERROR );
  199.                 EndDialog( hDlg, 0 );
  200.             }
  201.             break;
  202.         }
  203.  
  204.         case WM_APP_APPDISCONNECTED:
  205.         {
  206.             // This is an app defined msg that keeps the 
  207.             // lobby message handler from blocking on the dialog thread.
  208.             DPNHANDLE hDisconnectId = (DPNHANDLE) lParam;
  209.             HRESULT   hrReason      = (HRESULT) wParam;
  210.  
  211.             // Remove this connection from the list
  212.             TCHAR strBuffer[200];
  213.             wsprintf( strBuffer, TEXT("0x%x"), hDisconnectId );
  214.             int nIndex = (int) SendDlgItemMessage( g_hDlg, IDC_ACTIVE_CONNECTIONS, 
  215.                                                    LB_FINDSTRINGEXACT, -1, (LPARAM) strBuffer );
  216.             SendDlgItemMessage( g_hDlg, IDC_ACTIVE_CONNECTIONS, LB_DELETESTRING, nIndex, 0 );
  217.  
  218.             // Tell the user
  219.             wsprintf( strBuffer, TEXT("0x%x was disconnected. Reason: 0x%0.8x"), 
  220.                       hDisconnectId, hrReason );
  221.             MessageBox( g_hDlg, strBuffer, g_strAppName, MB_OK );
  222.             break;
  223.         }
  224.  
  225.         case WM_APP_SETSTATUS:
  226.         {
  227.             // This is an app defined msg that keeps the 
  228.             // lobby message handler from blocking on the dialog thread.
  229.             TCHAR* strBuffer = (TCHAR*) lParam;                     
  230.  
  231.             if( strBuffer )
  232.             {
  233.                 SetDlgItemText( g_hDlg, IDC_STATUS, strBuffer );
  234.                 SAFE_DELETE_ARRAY( strBuffer );
  235.             }
  236.             break;
  237.         }
  238.  
  239.         case WM_COMMAND:
  240.         {
  241.             switch( LOWORD(wParam) )
  242.             {
  243.                 case IDC_HOST_SESSION:
  244.                     SetupAddressFields( hDlg );
  245.                     break;
  246.  
  247.                 case IDC_SP_COMBO:
  248.                 {
  249.                     // If the pSPGuid changed then re-enum the adapters, and
  250.                     // update the address fields.
  251.                     int nSPIndex = (int) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETCURSEL, 0, 0 );
  252.                     GUID* pSPGuid = (GUID*) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETITEMDATA, nSPIndex, 0 );
  253.                     if( pSPGuid != NULL && g_pCurSPGuid != pSPGuid )
  254.                     {
  255.                         g_pCurSPGuid = pSPGuid;
  256.                         SetupAddressFields( hDlg );
  257.                         EnumAdapters( hDlg, pSPGuid );
  258.                     }
  259.                     break;
  260.                 }
  261.  
  262.                 case IDC_LAUNCH:
  263.                     if( FAILED( hr = LaunchApp( hDlg ) ) )
  264.                     {
  265.                         DXTRACE_ERR( TEXT("LaunchApp"), hr );
  266.                         MessageBox( NULL, TEXT("Failure trying to launch app. ")
  267.                                     TEXT("The sample will now quit."),
  268.                                     g_strAppName, MB_OK | MB_ICONERROR );
  269.                         EndDialog( hDlg, 0 );
  270.                     }
  271.                     break;
  272.  
  273.                 case IDC_SEND_MSG:
  274.                     // Send a dummy message to a connected app for demo purposes
  275.                     SendMsgToApp( hDlg );
  276.                     break;
  277.  
  278.                 case IDC_DISCONNECT:
  279.                     // Disconnect from an app
  280.                     DisconnectFromApp( hDlg );
  281.                     break;
  282.  
  283.                 case IDCANCEL:
  284.                     EndDialog( hDlg, 0 );
  285.                     return TRUE;
  286.             }
  287.             break;
  288.         }
  289.  
  290.         case WM_DESTROY:
  291.         {
  292.             GetDlgItemText( hDlg, IDC_PLAYER_NAME, g_strPlayerName, MAX_PATH );
  293.             GetDlgItemText( hDlg, IDC_SESSION_NAME, g_strSessionName, MAX_PATH );
  294.             int nIndex = (int) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETCURSEL, 0, 0 );
  295.             SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETLBTEXT, nIndex, (LPARAM) g_strPreferredProvider );
  296.  
  297.             GUID* pGuid;
  298.             int nCount,i;
  299.             nCount = (int)SendDlgItemMessage( hDlg, IDC_APP_LIST, LB_GETCOUNT, 0, 0 );
  300.             for( i=0; i<nCount; i++ )
  301.             {
  302.                 pGuid = (LPGUID) SendDlgItemMessage( hDlg, IDC_APP_LIST, LB_GETITEMDATA, i, 0 );
  303.                 SAFE_DELETE( pGuid );
  304.             }
  305.  
  306.             nCount = (int)SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETCOUNT, 0, 0 );
  307.             for( i=0; i<nCount; i++ )
  308.             {
  309.                 pGuid = (LPGUID) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETITEMDATA, i, 0 );
  310.                 SAFE_DELETE( pGuid );
  311.             }
  312.  
  313.             nCount = (int)SendDlgItemMessage( hDlg, IDC_ADAPTER_COMBO, CB_GETCOUNT, 0, 0 );
  314.             for( i=0; i<nCount; i++ )
  315.             {
  316.                 pGuid = (LPGUID) SendDlgItemMessage( hDlg, IDC_ADAPTER_COMBO, CB_GETITEMDATA, i, 0 );
  317.                 SAFE_DELETE( pGuid );
  318.             }
  319.  
  320.             break;
  321.         }
  322.     }
  323.  
  324.     return FALSE; // Didn't handle message
  325. }
  326.  
  327.  
  328.  
  329.  
  330. //-----------------------------------------------------------------------------
  331. // Name: OnInitDialog
  332. // Desc: 
  333. //-----------------------------------------------------------------------------
  334. HRESULT OnInitDialog( HWND hDlg )
  335. {
  336.     HRESULT hr;
  337.  
  338.     // Load and set the icon
  339.     HICON hIcon = LoadIcon( g_hInst, MAKEINTRESOURCE( IDI_MAIN ) );
  340.     SendMessage( hDlg, WM_SETICON, ICON_BIG,   (LPARAM) hIcon );  // Set big icon
  341.     SendMessage( hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon );  // Set small icon
  342.  
  343.     CheckDlgButton( hDlg, IDC_HOST_SESSION, BST_CHECKED );
  344.     CheckRadioButton( hDlg, IDC_LAUNCH_NEW, IDC_DONT_LAUNCH, IDC_LAUNCH_NOT_FOUND );
  345.  
  346.     SetDlgItemText( hDlg, IDC_PLAYER_NAME, g_strPlayerName );
  347.     SetDlgItemText( hDlg, IDC_SESSION_NAME, g_strSessionName );
  348.  
  349.     if( FAILED( hr = EnumRegisteredApplications( hDlg ) ) )
  350.         return DXTRACE_ERR( TEXT("EnumRegisteredApplications"), hr );
  351.  
  352.     if( FAILED( hr = EnumServiceProviders( hDlg ) ) )
  353.         return DXTRACE_ERR( TEXT("EnumServiceProviders"), hr );
  354.     
  355.     WSADATA WSAData;
  356.     _tcscpy( g_strLocalIP, TEXT("") );
  357.     if( WSAStartup (MAKEWORD(1,0), &WSAData) == 0) 
  358.     {
  359.         CHAR strLocalHostName[MAX_PATH];
  360.         gethostname( strLocalHostName, MAX_PATH );
  361.         HOSTENT* pHostEnt = gethostbyname( strLocalHostName );
  362.         if( pHostEnt )
  363.         {
  364.             in_addr* pInAddr = (in_addr*) pHostEnt->h_addr_list[0];
  365.             char* strLocalIP = inet_ntoa( *pInAddr );
  366.             if( strLocalIP )
  367.                 DXUtil_ConvertAnsiStringToGeneric( g_strLocalIP, strLocalIP );
  368.         }
  369.  
  370.         WSACleanup();
  371.     }
  372.     
  373.     SetupAddressFields( hDlg );
  374.  
  375.     int nSPIndex = (int) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETCURSEL, 0, 0 );
  376.     GUID* pSPGuid = (GUID*) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETITEMDATA, nSPIndex, 0 );
  377.     if( pSPGuid != NULL )
  378.     {
  379.         g_pCurSPGuid = pSPGuid;
  380.         EnumAdapters( hDlg, pSPGuid );
  381.     }
  382.  
  383.     return S_OK;
  384. }
  385.  
  386.  
  387.  
  388.  
  389. //-----------------------------------------------------------------------------
  390. // Name: SetupAddressFields
  391. // Desc: Based on the SP selected, update the address UI 
  392. //-----------------------------------------------------------------------------
  393. VOID SetupAddressFields( HWND hDlg )
  394. {
  395.     int nSPIndex = (int) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETCURSEL, 0, 0 );
  396.     if( nSPIndex == LB_ERR )
  397.         return;
  398.     GUID* pGuid = (GUID*) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETITEMDATA, nSPIndex, 0 );
  399.     if( pGuid == NULL )
  400.         return;
  401.  
  402.     BOOL bHosting = IsDlgButtonChecked( hDlg, IDC_HOST_SESSION );
  403.  
  404.     if( *pGuid == CLSID_DP8SP_TCPIP )
  405.     {
  406.         EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE2), TRUE );
  407.         SetDlgItemText( hDlg, IDC_ADDRESS_LINE2, TEXT("2323") );
  408.         EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE2_TEXT), TRUE );
  409.         SetDlgItemText( hDlg, IDC_ADDRESS_LINE2_TEXT, TEXT("Port:") );
  410.  
  411.         if( bHosting )
  412.         {
  413.             EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE1), FALSE );
  414.             SetDlgItemText( hDlg, IDC_ADDRESS_LINE1, TEXT("") );
  415.             EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE1_TEXT), FALSE );
  416.             SetDlgItemText( hDlg, IDC_ADDRESS_LINE1_TEXT, TEXT("") );
  417.         }
  418.         else
  419.         {
  420.             EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE1), TRUE );
  421.             SetDlgItemText( hDlg, IDC_ADDRESS_LINE1, g_strLocalIP );
  422.             EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE1_TEXT), TRUE );
  423.             SetDlgItemText( hDlg, IDC_ADDRESS_LINE1_TEXT, TEXT("IP Address:") );
  424.         }
  425.     }
  426.     else if( *pGuid == CLSID_DP8SP_MODEM )
  427.     {
  428.         EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE1), TRUE );
  429.         SetDlgItemText( hDlg, IDC_ADDRESS_LINE1, TEXT("") );
  430.         EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE1_TEXT), TRUE );
  431.         SetDlgItemText( hDlg, IDC_ADDRESS_LINE1_TEXT, TEXT("Phone Number:") );
  432.  
  433.         EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE2), FALSE );
  434.         SetDlgItemText( hDlg, IDC_ADDRESS_LINE2, TEXT("") );
  435.         EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE2_TEXT), FALSE );
  436.         SetDlgItemText( hDlg, IDC_ADDRESS_LINE2_TEXT, TEXT("") );
  437.     }
  438.     else 
  439.     {
  440.         // pGuid is CLSID_DP8SP_IPX or CLSID_DP8SP_SERIAL or unknown 
  441.         // so disable all the address lines 
  442.         EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE1), FALSE );
  443.         SetDlgItemText( hDlg, IDC_ADDRESS_LINE1, TEXT("") );
  444.         EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE1_TEXT), FALSE );
  445.         SetDlgItemText( hDlg, IDC_ADDRESS_LINE1_TEXT, TEXT("") );
  446.         EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE2), FALSE );
  447.         SetDlgItemText( hDlg, IDC_ADDRESS_LINE2, TEXT("") );
  448.         EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE2_TEXT), FALSE );
  449.         SetDlgItemText( hDlg, IDC_ADDRESS_LINE2_TEXT, TEXT("") );
  450.     }
  451. }
  452.  
  453.  
  454.  
  455.  
  456. //-----------------------------------------------------------------------------
  457. // Name: EnumRegisteredApplications
  458. // Desc: Enum all the lobby launchable apps and put them in the listbox
  459. //-----------------------------------------------------------------------------
  460. HRESULT EnumRegisteredApplications( HWND hDlg )
  461. {
  462.     HRESULT hr;
  463.     DWORD   dwSize     = 0;
  464.     DWORD   dwPrograms = 0;
  465.     DWORD   iProgram;
  466.     BYTE*   pData   = NULL;
  467.  
  468.     hr = g_pLobbyClient->EnumLocalPrograms( NULL, pData, &dwSize, &dwPrograms, 0 );
  469.     if( hr != DPNERR_BUFFERTOOSMALL && FAILED(hr) )
  470.         return DXTRACE_ERR( TEXT("EnumLocalPrograms"), hr );
  471.  
  472.     if( dwSize == 0 )
  473.     {
  474.         MessageBox( NULL, TEXT("There are no applications registered as lobby launchable. ")
  475.                     TEXT("The sample will now quit."),
  476.                     g_strAppName, MB_OK | MB_ICONERROR );
  477.         EndDialog( hDlg, 0 );
  478.         return S_OK;
  479.     }
  480.  
  481.     pData = new BYTE[dwSize];
  482.     if( FAILED( hr = g_pLobbyClient->EnumLocalPrograms( NULL, pData, &dwSize, &dwPrograms, 0 ) ) )
  483.         return DXTRACE_ERR( TEXT("EnumLocalPrograms"), hr );
  484.  
  485.     DPL_APPLICATION_INFO* pAppInfo = (DPL_APPLICATION_INFO*) pData;
  486.     for( iProgram=0; iProgram<dwPrograms; iProgram++ )
  487.     {
  488.         TCHAR strAppName[MAX_PATH];
  489.         DXUtil_ConvertWideStringToGeneric( strAppName, pAppInfo->pwszApplicationName );
  490.  
  491.         // Add the name to the listbox
  492.         int nIndex = (int) SendDlgItemMessage( hDlg, IDC_APP_LIST, LB_ADDSTRING, 0, (LPARAM) strAppName );
  493.  
  494.         // Store the guid in the listbox
  495.         GUID* pGuid = new GUID;
  496.         memcpy( pGuid, &pAppInfo->guidApplication, sizeof(GUID) );
  497.         SendDlgItemMessage( hDlg, IDC_APP_LIST, LB_SETITEMDATA, nIndex, (LPARAM) pGuid );
  498.  
  499.         pAppInfo++;
  500.     }
  501.  
  502.     SAFE_DELETE_ARRAY( pData );
  503.  
  504.     SendDlgItemMessage( hDlg, IDC_APP_LIST, LB_SETCURSEL, 0, 0 );
  505.  
  506.     return S_OK;
  507. }
  508.  
  509.  
  510.  
  511.  
  512. //-----------------------------------------------------------------------------
  513. // Name: EnumServiceProviders()
  514. // Desc: Fills the combobox with service providers
  515. //-----------------------------------------------------------------------------
  516. HRESULT EnumServiceProviders( HWND hDlg )
  517. {
  518.     DPN_SERVICE_PROVIDER_INFO* pdnSPInfo = NULL;
  519.     HRESULT hr;
  520.     DWORD   dwItems = 0;
  521.     DWORD   dwSize  = 0;
  522.     int     nIndex;
  523.  
  524.     // Enumerate all DirectPlay service providers, and store them in the listbox
  525.     hr = g_pDP->EnumServiceProviders( NULL, NULL, pdnSPInfo, &dwSize,
  526.                                       &dwItems, 0 );
  527.     if( hr != DPNERR_BUFFERTOOSMALL )
  528.         return DXTRACE_ERR( TEXT("EnumServiceProviders"), hr );
  529.  
  530.     pdnSPInfo = (DPN_SERVICE_PROVIDER_INFO*) new BYTE[dwSize];
  531.     if( FAILED( hr = g_pDP->EnumServiceProviders( NULL, NULL, pdnSPInfo,
  532.                                                   &dwSize, &dwItems, 0 ) ) )
  533.         return DXTRACE_ERR( TEXT("EnumServiceProviders"), hr );
  534.  
  535.     DPN_SERVICE_PROVIDER_INFO* pdnSPInfoEnum = pdnSPInfo;
  536.     for ( DWORD i = 0; i < dwItems; i++ )
  537.     {
  538.         TCHAR strName[MAX_PATH];
  539.         DXUtil_ConvertWideStringToGeneric( strName, pdnSPInfoEnum->pwszName );
  540.  
  541.         // Found a service provider, so put it in the listbox
  542.         nIndex = (int)SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_ADDSTRING, 
  543.                                               0, (LPARAM) strName );
  544.  
  545.         // Store pointer to GUID in listbox
  546.         GUID* pGuid = new GUID;
  547.         memcpy( pGuid, &pdnSPInfoEnum->guid, sizeof(GUID) );
  548.         SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_SETITEMDATA, 
  549.                             nIndex, (LPARAM) pGuid );
  550.  
  551.         pdnSPInfoEnum++;
  552.     }
  553.  
  554.     SAFE_DELETE_ARRAY( pdnSPInfo );
  555.  
  556.     // Try to select the default preferred provider
  557.     nIndex = (int)SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_FINDSTRINGEXACT, (WPARAM)-1,
  558.                                       (LPARAM)g_strPreferredProvider );
  559.     if( nIndex != LB_ERR )
  560.         SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_SETCURSEL, nIndex, 0 );
  561.     else
  562.         SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_SETCURSEL, 0, 0 );
  563.  
  564.     return S_OK;
  565. }
  566.  
  567.  
  568.  
  569.  
  570. //-----------------------------------------------------------------------------
  571. // Name: EnumAdapters()
  572. // Desc: Fills the combobox with adapters for a specified SP
  573. //-----------------------------------------------------------------------------
  574. HRESULT EnumAdapters( HWND hDlg, GUID* pSPGuid )
  575. {
  576.     DPN_SERVICE_PROVIDER_INFO* pdnSPInfo = NULL;
  577.     TCHAR   strName[MAX_PATH];
  578.     HRESULT hr;
  579.     DWORD   dwItems = 0;
  580.     DWORD   dwSize  = 0;
  581.     int     nIndex;
  582.     int     nAllAdaptersIndex = 0;
  583.  
  584.     SendDlgItemMessage( hDlg, IDC_ADAPTER_COMBO, CB_RESETCONTENT, 0, 0 );
  585.  
  586.     // Enumerate all DirectPlay service providers, and store them in the listbox
  587.     hr = g_pDP->EnumServiceProviders( pSPGuid, NULL, pdnSPInfo, &dwSize,
  588.                                       &dwItems, 0 );
  589.     if( hr != DPNERR_BUFFERTOOSMALL )
  590.         return DXTRACE_ERR( TEXT("EnumServiceProviders"), hr );
  591.  
  592.     pdnSPInfo = (DPN_SERVICE_PROVIDER_INFO*) new BYTE[dwSize];
  593.     if( FAILED( hr = g_pDP->EnumServiceProviders( pSPGuid, NULL, pdnSPInfo,
  594.                                                   &dwSize, &dwItems, 0 ) ) )
  595.         return DXTRACE_ERR( TEXT("EnumServiceProviders"), hr );
  596.  
  597.     DPN_SERVICE_PROVIDER_INFO* pdnSPInfoEnum = pdnSPInfo;
  598.     for ( DWORD i = 0; i < dwItems; i++ )
  599.     {
  600.         DXUtil_ConvertWideStringToGeneric( strName, pdnSPInfoEnum->pwszName );
  601.  
  602.         // Found a service provider, so put it in the listbox
  603.         nIndex = (int)SendDlgItemMessage( hDlg, IDC_ADAPTER_COMBO, CB_ADDSTRING, 
  604.                                           0, (LPARAM) strName );
  605.  
  606.         if( _tcscmp( strName, TEXT("All Adapters") ) == 0 )
  607.             nAllAdaptersIndex = nIndex;
  608.  
  609.         // Store pointer to GUID in listbox
  610.         GUID* pGuid = new GUID;
  611.         memcpy( pGuid, &pdnSPInfoEnum->guid, sizeof(GUID) );
  612.  
  613.         SendDlgItemMessage( hDlg, IDC_ADAPTER_COMBO, CB_SETITEMDATA, 
  614.                             nIndex, (LPARAM) pGuid );
  615.  
  616.         pdnSPInfoEnum++;
  617.     }
  618.  
  619.     SAFE_DELETE_ARRAY( pdnSPInfo );
  620.  
  621.     SendDlgItemMessage( hDlg, IDC_ADAPTER_COMBO, CB_SETCURSEL, nAllAdaptersIndex, 0 );
  622.  
  623.     return S_OK;
  624. }
  625.  
  626.  
  627.  
  628.  
  629. //-----------------------------------------------------------------------------
  630. // Name: LaunchApp
  631. // Desc: Launch the selected app based on the UI settings
  632. //-----------------------------------------------------------------------------
  633. HRESULT LaunchApp( HWND hDlg )
  634. {
  635.     HRESULT   hr;
  636.     DPNHANDLE hApplication = NULL;
  637.  
  638.     BOOL bLaunchNew      = IsDlgButtonChecked( hDlg, IDC_LAUNCH_NEW );
  639.     BOOL bLaunchNotFound = IsDlgButtonChecked( hDlg, IDC_LAUNCH_NOT_FOUND );
  640.  
  641.     int nAppIndex = (int) SendDlgItemMessage( hDlg, IDC_APP_LIST, LB_GETCURSEL, 0, 0 );
  642.     GUID* pAppGuid = (GUID*) SendDlgItemMessage( hDlg, IDC_APP_LIST, LB_GETITEMDATA, nAppIndex, 0 );
  643.     if( nAppIndex == LB_ERR || pAppGuid == NULL )
  644.         return E_INVALIDARG;
  645.  
  646.     // Setup the DPL_CONNECT_INFO struct
  647.     DPL_CONNECT_INFO dnConnectInfo;
  648.     ZeroMemory( &dnConnectInfo, sizeof(DPL_CONNECT_INFO) );
  649.     dnConnectInfo.dwSize = sizeof(DPL_CONNECT_INFO);
  650.     dnConnectInfo.pvLobbyConnectData = NULL;
  651.     dnConnectInfo.dwLobbyConnectDataSize = 0;
  652.     dnConnectInfo.dwFlags = 0;
  653.     if( bLaunchNew )
  654.         dnConnectInfo.dwFlags |= DPLCONNECT_LAUNCHNEW;
  655.     if( bLaunchNotFound )
  656.         dnConnectInfo.dwFlags |= DPLCONNECT_LAUNCHNOTFOUND;
  657.     dnConnectInfo.guidApplication = *pAppGuid;
  658.     if( FAILED( hr = AllocAndInitConnectSettings( hDlg, pAppGuid, &dnConnectInfo.pdplConnectionSettings ) ) ) 
  659.         return S_FALSE;
  660.  
  661.     hr = g_pLobbyClient->ConnectApplication( &dnConnectInfo, NULL, &hApplication, 
  662.                                              INFINITE, 0 );
  663.     if( FAILED(hr) )
  664.     {
  665.         if( hr == DPNERR_NOCONNECTION && !bLaunchNew && !bLaunchNotFound )
  666.         {
  667.             MessageBox( NULL, TEXT("There was no waiting application. "),
  668.                         g_strAppName, MB_OK | MB_ICONERROR );
  669.         }
  670.         else
  671.         {
  672.             return DXTRACE_ERR( TEXT("ConnectApplication"), hr );
  673.         }
  674.     }
  675.     else
  676.     {
  677.         TCHAR strBuffer[20];
  678.         wsprintf( strBuffer, TEXT("0x%x"), hApplication );
  679.         int nIndex = (int) SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS, LB_ADDSTRING, 
  680.                                          0, (LPARAM) strBuffer );
  681.         SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS, LB_SETITEMDATA, 
  682.                             nIndex, (LPARAM) hApplication );
  683.  
  684.         if( LB_ERR == SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS, LB_GETCURSEL, 0, 0 ) )
  685.             SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS, LB_SETCURSEL, 0, 0 );
  686.     }
  687.  
  688.     FreeConnectSettings( dnConnectInfo.pdplConnectionSettings );
  689.  
  690.     return S_OK;
  691. }
  692.  
  693.  
  694.  
  695.  
  696. //-----------------------------------------------------------------------------
  697. // Name: AllocAndInitConnectSettings
  698. // Desc: Alloc and fill up a DPL_CONNECTION_SETTINGS.  Call FreeConnectSettings
  699. //       later to free it.
  700. //-----------------------------------------------------------------------------
  701. HRESULT AllocAndInitConnectSettings( HWND hDlg, GUID* pAppGuid, 
  702.                                      DPL_CONNECTION_SETTINGS** ppdplConnectSettings ) 
  703. {
  704.     HRESULT hr;
  705.  
  706.     BOOL bHosting    = IsDlgButtonChecked( hDlg, IDC_HOST_SESSION );
  707.     BOOL bNoSettings = IsDlgButtonChecked( hDlg, IDC_NO_SETTINGS );
  708.     IDirectPlay8Address* pHostAddress   = NULL;
  709.     IDirectPlay8Address* pDeviceAddress = NULL;
  710.  
  711.     if( bNoSettings )
  712.     {
  713.         *ppdplConnectSettings = NULL;
  714.         return S_OK;
  715.     }
  716.  
  717.     int nSPIndex = (int) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETCURSEL, 0, 0 );
  718.     GUID* pSPGuid = (GUID*) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETITEMDATA, nSPIndex, 0 );
  719.  
  720.     if( *pSPGuid == CLSID_DP8SP_IPX && !bHosting )
  721.     {
  722.         MessageBox( hDlg, TEXT("A typical lobby client would have sent a complete IPX address, this ") \
  723.                           TEXT("lobby client does not support this. "), g_strAppName, MB_OK );
  724.         return E_NOTIMPL;
  725.     }
  726.  
  727.     if( !bHosting )
  728.     {
  729.         // Create a host address if connecting to a host, 
  730.         // otherwise keep it as NULL
  731.         if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Address, NULL, CLSCTX_INPROC_SERVER, 
  732.                                            IID_IDirectPlay8Address, (void **) &pHostAddress ) ) )
  733.             return DXTRACE_ERR( TEXT("CoCreateInstance"), hr );
  734.  
  735.         // Set the SP to pHostAddress
  736.         if( FAILED( hr = pHostAddress->SetSP( pSPGuid ) ) )
  737.             return DXTRACE_ERR( TEXT("SetSP"), hr );
  738.     }
  739.  
  740.     // Create a device address to specify which device we are using 
  741.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Address, NULL, CLSCTX_INPROC_SERVER, 
  742.                                        IID_IDirectPlay8Address, (void **) &pDeviceAddress ) ) )
  743.         return DXTRACE_ERR( TEXT("CoCreateInstance"), hr );
  744.  
  745.     // Set the SP to pDeviceAddress
  746.     if( FAILED( hr = pDeviceAddress->SetSP( pSPGuid ) ) )
  747.         return DXTRACE_ERR( TEXT("SetSP"), hr );
  748.  
  749.     // Add the adapter to pHostAddress
  750.     int nAdapterIndex = (int) SendDlgItemMessage( hDlg, IDC_ADAPTER_COMBO, CB_GETCURSEL, 0, 0 );
  751.     GUID* pAdapterGuid = (GUID*) SendDlgItemMessage( hDlg, IDC_ADAPTER_COMBO, CB_GETITEMDATA, 
  752.                                                      nAdapterIndex, 0 );
  753.     if( FAILED( hr = pDeviceAddress->SetDevice( pAdapterGuid ) ) )
  754.         return DXTRACE_ERR( TEXT("SetDevice"), hr );
  755.  
  756.     if( *pSPGuid == CLSID_DP8SP_TCPIP )
  757.     {
  758.         TCHAR strIP[MAX_PATH];
  759.         TCHAR strPort[MAX_PATH];
  760.  
  761.         GetDlgItemText( hDlg, IDC_ADDRESS_LINE1, strIP, MAX_PATH );
  762.         GetDlgItemText( hDlg, IDC_ADDRESS_LINE2, strPort, MAX_PATH );
  763.  
  764.         if( bHosting )
  765.         {
  766.             // Add the port to pDeviceAddress
  767.             DWORD dwPort = _ttoi( strPort );
  768.             if( FAILED( hr = pDeviceAddress->AddComponent( DPNA_KEY_PORT, 
  769.                                                            &dwPort, sizeof(dwPort),
  770.                                                            DPNA_DATATYPE_DWORD ) ) )
  771.                 return DXTRACE_ERR( TEXT("AddComponent"), hr );
  772.         }
  773.         else
  774.         {
  775.             // Add the IP address to pHostAddress
  776.             if( _tcslen( strIP ) > 0 )
  777.             {
  778.                 WCHAR wstrIP[MAX_PATH];
  779.                 DXUtil_ConvertGenericStringToWide( wstrIP, strIP );
  780.  
  781.                 if( FAILED( hr = pHostAddress->AddComponent( DPNA_KEY_HOSTNAME, 
  782.                                                              wstrIP, (wcslen(wstrIP)+1)*sizeof(WCHAR), 
  783.                                                              DPNA_DATATYPE_STRING ) ) )
  784.                     return DXTRACE_ERR( TEXT("AddComponent"), hr );
  785.             }
  786.  
  787.             // Add the port to pHostAddress
  788.             DWORD dwPort = _ttoi( strPort );
  789.             if( FAILED( hr = pHostAddress->AddComponent( DPNA_KEY_PORT, 
  790.                                                          &dwPort, sizeof(dwPort),
  791.                                                          DPNA_DATATYPE_DWORD ) ) )
  792.                 return DXTRACE_ERR( TEXT("AddComponent"), hr );
  793.         }
  794.     }
  795.     else if( *pSPGuid == CLSID_DP8SP_MODEM )
  796.     {
  797.         TCHAR strPhone[MAX_PATH];
  798.         GetDlgItemText( hDlg, IDC_ADDRESS_LINE1, strPhone, MAX_PATH );
  799.  
  800.         if( !bHosting )
  801.         {
  802.             // Add the phonenumber to pHostAddress
  803.             if( _tcslen( strPhone ) > 0 )
  804.             {
  805.                 WCHAR wstrPhone[MAX_PATH];
  806.                 DXUtil_ConvertGenericStringToWide( wstrPhone, strPhone );
  807.  
  808.                 if( FAILED( hr = pHostAddress->AddComponent( DPNA_KEY_PHONENUMBER, 
  809.                                                              wstrPhone, (wcslen(wstrPhone)+1)*sizeof(WCHAR), 
  810.                                                              DPNA_DATATYPE_STRING ) ) )
  811.                     return DXTRACE_ERR( TEXT("AddComponent"), hr );
  812.             }
  813.         }
  814.     }
  815.     else if( *pSPGuid == CLSID_DP8SP_SERIAL )
  816.     {
  817.         // This simple client doesn't have UI to query for the various
  818.         // fields needed for the serial.  So we just let DPlay popup a dialog
  819.         // to ask the user which settings are needed.
  820.     }
  821.     else
  822.     {
  823.         // Unknown SP, so leave as is
  824.     }
  825.  
  826.     // Setup the DPL_CONNECTION_SETTINGS
  827.     DPL_CONNECTION_SETTINGS* pSettings = new DPL_CONNECTION_SETTINGS;
  828.     ZeroMemory( pSettings, sizeof(DPL_CONNECTION_SETTINGS) );
  829.     pSettings->dwSize = sizeof(DPL_CONNECTION_SETTINGS);
  830.     pSettings->dpnAppDesc.dwSize = sizeof(DPN_APPLICATION_DESC);
  831.     pSettings->dwFlags = 0;
  832.     if( bHosting )
  833.         pSettings->dwFlags |= DPLCONNECTSETTINGS_HOST;
  834.     pSettings->dpnAppDesc.guidApplication = *pAppGuid;
  835.     pSettings->dpnAppDesc.guidInstance    = GUID_NULL;
  836.     pSettings->pdp8HostAddress = pHostAddress;
  837.     pSettings->ppdp8DeviceAddresses = new IDirectPlay8Address*;
  838.     pSettings->ppdp8DeviceAddresses[0] = pDeviceAddress;
  839.     pSettings->cNumDeviceAddresses = 1;
  840.  
  841.     // Set the pSettings->dpnAppDesc.pwszSessionName
  842.     TCHAR strSessionName[MAX_PATH];
  843.     GetDlgItemText( hDlg, IDC_SESSION_NAME, strSessionName, MAX_PATH );
  844.     if( _tcslen( strSessionName ) == 0 )
  845.     {
  846.         pSettings->dpnAppDesc.pwszSessionName = NULL;
  847.     }
  848.     else
  849.     {
  850.         WCHAR wstrSessionName[MAX_PATH];
  851.         DXUtil_ConvertGenericStringToWide( wstrSessionName, strSessionName );
  852.         pSettings->dpnAppDesc.pwszSessionName = new WCHAR[wcslen(wstrSessionName)+1];
  853.         wcscpy( pSettings->dpnAppDesc.pwszSessionName, wstrSessionName );
  854.     }
  855.  
  856.     // Set the pSettings->pwszPlayerName
  857.     TCHAR strPlayerName[MAX_PATH];
  858.     GetDlgItemText( hDlg, IDC_PLAYER_NAME, strPlayerName, MAX_PATH );
  859.     if( _tcslen( strPlayerName ) == 0 )
  860.     {
  861.         pSettings->pwszPlayerName = NULL;
  862.     }
  863.     else
  864.     {
  865.         WCHAR wstrPlayerName[MAX_PATH];
  866.         DXUtil_ConvertGenericStringToWide( wstrPlayerName, strPlayerName );
  867.         pSettings->pwszPlayerName = new WCHAR[wcslen(wstrPlayerName)+1];
  868.         wcscpy( pSettings->pwszPlayerName, wstrPlayerName );
  869.     }
  870.  
  871.     *ppdplConnectSettings = pSettings;
  872.  
  873.     return S_OK;
  874. }
  875.  
  876.  
  877.  
  878.  
  879. //-----------------------------------------------------------------------------
  880. // Name: FreeConnectSettings
  881. // Desc: Releases everything involved in a DPL_CONNECTION_SETTINGS struct
  882. //-----------------------------------------------------------------------------
  883. VOID FreeConnectSettings( DPL_CONNECTION_SETTINGS* pSettings )
  884. {
  885.     if( !pSettings )
  886.         return;
  887.  
  888.     SAFE_DELETE_ARRAY( pSettings->pwszPlayerName ); 
  889.     SAFE_DELETE_ARRAY( pSettings->dpnAppDesc.pwszSessionName );
  890.     SAFE_DELETE_ARRAY( pSettings->dpnAppDesc.pwszPassword );
  891.     SAFE_DELETE_ARRAY( pSettings->dpnAppDesc.pvReservedData );
  892.     SAFE_DELETE_ARRAY( pSettings->dpnAppDesc.pvApplicationReservedData );
  893.     SAFE_RELEASE( pSettings->pdp8HostAddress );
  894.     SAFE_RELEASE( pSettings->ppdp8DeviceAddresses[0] );
  895.     SAFE_DELETE_ARRAY( pSettings->ppdp8DeviceAddresses );
  896.     SAFE_DELETE( pSettings );
  897. }
  898.  
  899.  
  900.  
  901.  
  902. //-----------------------------------------------------------------------------
  903. // Name: DirectPlayMessageHandler
  904. // Desc: Handler for DirectPlay messages.  This function is called by
  905. //       the DirectPlay message handler pool of threads, so be care of thread
  906. //       synchronization problems with shared memory
  907. //-----------------------------------------------------------------------------
  908. HRESULT WINAPI DirectPlayMessageHandler( PVOID pvUserContext, 
  909.                                          DWORD dwMessageId, 
  910.                                          PVOID pMsgBuffer )
  911. {
  912.     return S_OK;
  913. }
  914.  
  915.  
  916.  
  917.  
  918. //-----------------------------------------------------------------------------
  919. // Name: DirectPlayLobbyMessageHandler
  920. // Desc: Handler for DirectPlay lobby messages.  This function is called by
  921. //       the DirectPlay lobby message handler pool of threads, so be careful of 
  922. //       thread synchronization problems with shared memory
  923. //-----------------------------------------------------------------------------
  924. HRESULT WINAPI DirectPlayLobbyMessageHandler( PVOID pvUserContext, 
  925.                                               DWORD dwMessageId, 
  926.                                               PVOID pMsgBuffer )
  927. {
  928.     switch( dwMessageId )
  929.     {
  930.         case DPL_MSGID_DISCONNECT:
  931.         {
  932.             PDPL_MESSAGE_DISCONNECT pDisconnectMsg;
  933.             pDisconnectMsg = (PDPL_MESSAGE_DISCONNECT)pMsgBuffer;
  934.  
  935.             // We should free any data associated with the 
  936.             // app here, but there is none.
  937.  
  938.             // Tell the update the UI so show that a application was disconnected
  939.             // Note: The lobby handler must not become blocked on the dialog thread, 
  940.             // since the dialog thread will be blocked on lobby handler thread
  941.             // when it calls ConnectApplication().  So to avoid blocking on
  942.             // the dialog thread, we'll post a message to the dialog thread.
  943.             PostMessage( g_hDlg, WM_APP_APPDISCONNECTED, 0, pDisconnectMsg->hDisconnectId );            
  944.             break;
  945.         }
  946.  
  947.         case DPL_MSGID_RECEIVE:
  948.         {
  949.             PDPL_MESSAGE_RECEIVE pReceiveMsg;
  950.             pReceiveMsg = (PDPL_MESSAGE_RECEIVE)pMsgBuffer;
  951.  
  952.             // The lobby app sent us data.  This sample doesn't
  953.             // expected data from the app, but it is useful 
  954.             // for more complex lclients.
  955.             break;
  956.         }
  957.  
  958.         case DPL_MSGID_SESSION_STATUS:
  959.         {
  960.             PDPL_MESSAGE_SESSION_STATUS pStatusMsg;
  961.             pStatusMsg = (PDPL_MESSAGE_SESSION_STATUS)pMsgBuffer;
  962.  
  963.             TCHAR* strBuffer = new TCHAR[200];
  964.             wsprintf( strBuffer, TEXT("0x%x: "), pStatusMsg->hSender );
  965.             switch( pStatusMsg->dwStatus )
  966.             {
  967.                 case DPLSESSION_CONNECTED:
  968.                     _tcscat( strBuffer, TEXT("Session connected") ); break;
  969.                 case DPLSESSION_COULDNOTCONNECT:
  970.                     _tcscat( strBuffer, TEXT("Session could not connect") ); break;
  971.                 case DPLSESSION_DISCONNECTED:
  972.                     _tcscat( strBuffer, TEXT("Session disconnected") ); break;
  973.                 case DPLSESSION_TERMINATED:
  974.                     _tcscat( strBuffer, TEXT("Session terminated") ); break;
  975.                 case DPLSESSION_HOSTMIGRATED:
  976.                     _tcscat( strBuffer, TEXT("Host migrated") ); break;
  977.                 case DPLSESSION_HOSTMIGRATEDHERE:
  978.                     _tcscat( strBuffer, TEXT("Host migrated to this client") ); break;
  979.  
  980.                 default:
  981.                 {
  982.                     TCHAR strStatus[30];
  983.                     wsprintf( strStatus, TEXT("%d"), pStatusMsg->dwStatus );
  984.                     _tcscat( strBuffer, strStatus );
  985.                     break;
  986.                 }
  987.             }
  988.  
  989.             // Tell the update the UI so show that a application status changed
  990.             // Note: The lobby handler must not become blocked on the dialog thread, 
  991.             // since the dialog thread will be blocked on lobby handler thread
  992.             // when it calls ConnectApplication().  So to avoid blocking on
  993.             // the dialog thread, we'll post a message to the dialog thread.
  994.             PostMessage( g_hDlg, WM_APP_SETSTATUS, 0, (LPARAM) strBuffer );            
  995.             break;
  996.         }
  997.  
  998.         case DPL_MSGID_CONNECTION_SETTINGS:
  999.         {
  1000.             PDPL_MESSAGE_CONNECTION_SETTINGS pConnectionStatusMsg;
  1001.             pConnectionStatusMsg = (PDPL_MESSAGE_CONNECTION_SETTINGS)pMsgBuffer;
  1002.  
  1003.             // The app has changed the connection settings.  
  1004.             // This simple client doesn't handle this, but more complex clients may
  1005.             // want to.
  1006.             break;
  1007.         }
  1008.     }
  1009.  
  1010.     return S_OK;
  1011. }
  1012.  
  1013.  
  1014.  
  1015.  
  1016. //-----------------------------------------------------------------------------
  1017. // Name: SendMsgToApp
  1018. // Desc: Send a dummy message to a connected app for demo purposes 
  1019. //-----------------------------------------------------------------------------
  1020. HRESULT SendMsgToApp( HWND hDlg )
  1021. {
  1022.     TCHAR strBuffer[MAX_PATH];
  1023.     HRESULT hr;
  1024.  
  1025.     int nConnectIndex = (int) SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS, LB_GETCURSEL, 0, 0 );
  1026.     if( nConnectIndex == LB_ERR )
  1027.         return S_OK;
  1028.  
  1029.     DPNHANDLE hApplication = (DPNHANDLE) SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS, 
  1030.                                                              LB_GETITEMDATA, nConnectIndex, 0 );
  1031.  
  1032.     // For demonstration purposes, just send a buffer to the app.  This can be used
  1033.     // by more complex lobby clients to pass custom information to apps that which
  1034.     // can then recieve and process it.
  1035.     BYTE buffer[20];
  1036.     memset( buffer, 0x03, 20 );
  1037.     if( FAILED( hr = g_pLobbyClient->Send( hApplication, buffer, 20, 0 ) ) )
  1038.     {
  1039.         DXTRACE_ERR( TEXT("Send"), hr );
  1040.         wsprintf( strBuffer, TEXT("Failure trying to send message to 0x%0.8x."), hApplication );
  1041.         MessageBox( NULL, strBuffer, g_strAppName, MB_OK | MB_ICONERROR );
  1042.     }
  1043.     else
  1044.     {
  1045.         wsprintf( strBuffer, TEXT("Successfully sent a message to 0x%0.8x."), hApplication );
  1046.         MessageBox( NULL, strBuffer, g_strAppName, MB_OK | MB_ICONERROR );
  1047.     }
  1048.  
  1049.     return S_OK;
  1050. }
  1051.  
  1052.  
  1053.  
  1054.  
  1055. //-----------------------------------------------------------------------------
  1056. // Name: DisconnectFromApp
  1057. // Desc: Disconnect from an app
  1058. //-----------------------------------------------------------------------------
  1059. HRESULT DisconnectFromApp( HWND hDlg )
  1060. {
  1061.     HRESULT hr;
  1062.  
  1063.     int nConnectIndex = (int) SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS, LB_GETCURSEL, 0, 0 );
  1064.     if( nConnectIndex == LB_ERR )
  1065.         return S_OK;
  1066.  
  1067.     DPNHANDLE hApplication = (DPNHANDLE) SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS, 
  1068.                                                              LB_GETITEMDATA, nConnectIndex, 0 );
  1069.  
  1070.     if( FAILED( hr = g_pLobbyClient->ReleaseApplication( hApplication, 0 ) ) )
  1071.     {
  1072.         DXTRACE_ERR( TEXT("LaunchApp"), hr );
  1073.         MessageBox( NULL, TEXT("Failure trying to disconnect from app. "), 
  1074.                     g_strAppName, MB_OK | MB_ICONERROR );
  1075.     }
  1076.  
  1077.     SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS, LB_DELETESTRING, nConnectIndex, 0 );
  1078.  
  1079.     return S_OK;
  1080. }
  1081.  
  1082.